package com.jc.nio.process;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.Channel;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.util.StringTokenizer;

import com.jc.nio.handlers.NioHandler;

/**
 * 负责具体的Http处理，本例子主要模仿的get操作
 * 
 * @author Joeson
 * @since 2014/05
 * @version 01
 * 
 */
public class HttpOperation
{

	/**
	 * 响应头中的转行符
	 */
	private static final String CRLF = "\r\n";

	private ByteBuffer send = null;

	private Processor processor = null;

	public HttpOperation(Processor processor)
	{
		this.processor = processor;
	}

	/**
	 * 进行属性初始化
	 * 
	 * @param send
	 * @param handler
	 */
	public void initAttribute(ByteBuffer send)
	{
		this.send = send;
	}

	/**
	 * 根据请求文件是否存在、文件类型、文件名，返回一个需要响应的ByteBuffer
	 * 
	 * @param fileExists
	 *            请求的文件是否存在
	 * @param fileType
	 *            请求的文件类型是否支持
	 * @param fileName
	 *            请求文件名
	 * @return
	 */
	public void get(boolean fileExists, boolean fileType, String fileName)
	{
		FileInputStream fis = null;
		// 响应头的参数
		String serverLine = "Server:WebServer Test";
		String statusLine = null;
		String contentTypeLine = null;
		String entityBody = null;
		String contentLengthLine = "error";

		// 文件正常响应的情况
		if (fileExists && fileType)
		{
			statusLine = "HTTP/1.1 200 OK" + CRLF;
			contentTypeLine = "Content-type:" + contentType(fileName) + CRLF;

			try
			{
				fis = new FileInputStream(fileName);
				contentLengthLine = "Content-Length:" + fis.available() + CRLF;
			} catch (FileNotFoundException e)
			{
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e)
			{
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

		}
		else
		{
			if (fileExists && fileType == false)
			{
				statusLine = "HTTP/1.0 400 BadRequest" + CRLF;
				contentTypeLine = "text/html";
				entityBody = "<HTML>400 Not BadRequest</TITLE></HEAD>"
						+ "<BODY>400 BadRequest"
						+ "<br>usage:http://localhost:8080" + fileName
						+ "</BODY></HTML>";
			}
			else
				if (fileExists == false)
				{
					statusLine = "HTTP/1.0 404 Not Found" + CRLF;
					contentTypeLine = "text/html";
					entityBody = "<HTML>404 Not Found</TITLE></HEAD>"
							+ "<BODY>404 Not Found"
							+ "<br>usage:http://localhost:8080" + fileName
							+ "not found</BODY></HTML>";
				}
		}

		send.clear();
		// 将响应头信息都加入缓冲区中
		send.put(statusLine.getBytes());
		send.put(serverLine.getBytes());
		send.put(contentTypeLine.getBytes());
		send.put(contentLengthLine.getBytes());
		send.put(CRLF.getBytes());

		if (fileExists && fileType)
		{
			readFile(send, fis);
		}
		else
		{
			send.put(entityBody.getBytes());
		}
	}

	/**
	 * 对响应进行处理
	 * 
	 * @param msg
	 */
	public void process(String msg)
	{
		boolean fileExists = false;
		boolean fileType = false;

		StringTokenizer tokenizer = new StringTokenizer(msg);

		String temp = tokenizer.nextToken();
		if (temp.equals("GET"))
		{
			String fileName = tokenizer.nextToken();
			fileName = "." + fileName;

			// 如果请求文件是.htm/.html结尾的
			if (fileName.endsWith(".htm") || fileName.endsWith(".html")
					|| fileName.endsWith(".js") || fileName.endsWith(".css")
					|| fileName.endsWith(".png") || fileName.endsWith(".jpg")
					|| fileName.endsWith(".gif") || fileName.endsWith(".flv"))
			{
				System.out.println("=======================");
				System.out.println(fileName);
				System.out.println("=======================");
				File file = new File(fileName);

				fileExists = file.exists();
				fileType = true;
			}
			else
			{
				fileType = false;
				fileExists = false;
			}

			// 回调设置fileName、fileExists、fileType
			processor.setFileExists(fileExists);
			processor.setFileType(fileType);
			processor.setFileName(fileName);

		}// ends if(equals("GET"))
	}

	/**
	 * 返回contentType，根据fileName文件结尾判断，来判断contentType的类型
	 * 
	 * @param fileName
	 * @return
	 */
	private static String contentType(String fileName)
	{
		// html页面
		if (fileName.endsWith(".htm") || fileName.endsWith(".html"))
		{
			return "text/html";
		}
		if (fileName.endsWith(".css"))
		{
			return "text/css";
		}
		if (fileName.endsWith(".js"))
		{
			return "application/javascript";
		}
		if (fileName.endsWith(".png"))
		{
			return "image/png";
		}
		if (fileName.endsWith(".jpg") || fileName.endsWith(".jpeg"))
		{
			return "image/jpeg";
		}
		if (fileName.endsWith(".gif"))
		{
			return "image/gif";
		}
		if (fileName.endsWith(".flv"))
		{
			return "application/octet-stream";
		}

		return "fileName";
	}

	private ByteBuffer readFile(ByteBuffer send, FileInputStream fis)
	{
		FileChannel fileChannel = null;
		try
		{
			fileChannel = fis.getChannel();
			fileChannel.read(send);

		} catch (FileNotFoundException e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e)
		{
			e.printStackTrace();
		} finally
		{
			if (fileChannel != null)
			{
				try
				{
					fileChannel.close();
				} catch (IOException e)
				{
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}

			return send;
		}
	}
}
